// ---------------------------------- time format
console.log("\n")
console.log("--------------------")

const {dateFormat} = require('./timeParse')
const date = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
console.log("_server$ _当前运行时间: " + date)
// ---------------------------------- server main
const express = require('express')
const socketio = require('socket.io')
const path = require('path')
const http = require('http')

const {getRoomUsers, userJoin, userLeave, userInRoom} = require('./user')
const {roomJoinList, getRoomList, roomDismiss,} = require('./room')


// 这里把客户端也挂在了上去
// tips: 实时通讯三种方式 -长连接 -轮询 -websocket
const app = express();
const server = http.createServer(app);
const io = socketio(server);

/* websocket 关键字
   on   : 听
   emit : 讲
* */

// 监听客户端是否连接
/* on 和 emit 的参数: ( 消息类型 , 消息内容 )
*  指定同样的消息类型 , 才能听得到 , ok? */

/* 定义消息类型:
*  - 系统消息        : sysMessage
*  - 聊添消息        : chatMessage
*  - 加入房间消息     : joinRoom
*  - 房间用户列表消息  : roomUser
*  - 房间列表消息      : roomList
* */

// 全局,检测到 "connection" 连接之后 , 对该 connection 进行的操作
io.on("connection", (socket) => {


    // socket join 某个room
    // 具体 socket.join 的意义请看 https://socket.io/docs/v3/rooms/
    socket.on("joinRoom", ({name, room}) => {
        socket.join(room)

        // 将建立连接的 user 加入房间的列表
        // 这个 id 是本socket连接的 id ,
        // TODO:怎么充当 user 的id我还没有想清楚 , 是不是会被废弃呢
        console.log("加入信息:用户:" + name + "\t房间:" + room)

        userJoin(socket.id, name, room)
        io.to(room).emit("roomUser", getRoomUsers(room))

        // 到指定的 socket room 进行操作
        // 所有服务端向客户度发起的消息传输 应当加入 to(room)
        // 保证消息只传输到应当传输的 room 当中


        // 将房间 加入房间列表 , 并推送给其他人
        roomJoinList(room)
        io.emit("roomList", getRoomList())


        // 启动后自动向客户端发送系统消息 -> 进入聊天室消息
        // TODO: 这里没有办法让发出 sysMessage 的客户端接收到服务器发给自己的 sysMessage , 要解决
        // [sysMessage]message.type     : 系统信息类型 : "enterBroadCast" "exitBroadCast" ""
        // [sysMessage]message.name     : 系统信息首要指明对象
        // [sysMessage]message.room     : 房间号
        // [sysMessage]message.welcome  : 欢迎词
        // [sysMessage]message.time     : 获得服务器的 时间戳
        socket.to(room).emit("sysMessage", {
            type: "enterBroadCast",
            name: name,
            room: room,
            welcome: `欢迎加入${room}`,
            time: dateFormat("YYYY-mm-dd HH:MM:SS", new Date()),
        })

        // 监听客户端的聊添消息
        // [chatMessage]message.name
        // [chatMessage]message.content
        // [chatMessage]message.time
        socket.on("chatMessage", message => {
            console.log("S_on: " + room + message.name + " : " + message.content)

            // NOTE:
            // 这里的 io 是一个全局的 server 对象
            // 上面的 socket 只是一个 io 里的内部 server 对象
            // 所以 socket 算是在部分处理 , 但是 io 算是全局处理
            // 这里就是把接收到的消息推给所有人
            io.to(room).emit('chatMessage', message)
        })

        // fixme:这里犯了一个嵌套的错误 , 搞了一上午 , ctm

        // 监听socket disconnection 事件
        socket.on("disconnect", () => {
            // 返回一下 用户所在房间的 其他人的信息
            // 如果用户所在房间没有其他人 ,
            // 则从房间列表删除这个房间
            // 并广播更新房间列表
            let list_existUser = userInRoom(socket.id)
            // console.log(list_existUser)
            if (list_existUser.length === 0) {
                roomDismiss(room)
            }
            io.emit("roomList", getRoomList())


            // 从用户列表删除这个用户
            // user.js 脚本中删除
            userLeave(socket.id)
            // console.log("leave: |id:_" + socket.id + "|name:_" + name)

            // 重复把更新的用户列表发送一下
            io.to(room).emit("roomUser", getRoomUsers(room))

        })
    })


})

// 定义端口号
const PORT = process.env.PORT || 9527;

// express挂载文件
app.use(express.static(__dirname))

// 挂载文件到端口
server.listen(PORT, () => {
        console.log("_server$ 文件路径: " + __dirname);
        console.log("_server$ 服务端口: " + PORT);
        console.log("_server$ 打开连接: http://localhost:" + PORT);
    }
)